package com.ldzg.blockwatcher.watcher.eth;

import com.ldzg.blockwatcher.config.eth.EthProperties;
import com.ldzg.blockwatcher.constants.EthConstants;
import com.ldzg.blockwatcher.notify.enums.NotifySourceEnum;
import com.ldzg.blockwatcher.notify.factory.NotifyFactory;
import com.ldzg.blockwatcher.watcher.AbstractWatcher;
import io.reactivex.disposables.Disposable;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.web3j.abi.EventEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Event;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.request.EthFilter;
import org.web3j.protocol.core.methods.response.Log;

import java.util.List;

import static org.web3j.protocol.core.DefaultBlockParameterName.EARLIEST;
import static org.web3j.protocol.core.DefaultBlockParameterName.LATEST;

/**
 *  以太坊冻结数据监听
 *
 * @author 18310740596@163.com
 * @version V1.0.0
 * @since 2025-07-02 15:38:06
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EthAddedBlackListWatcher extends AbstractWatcher {

    private final Web3j web3j;
    private final EthProperties properties;

    private final NotifyFactory notifyFactory;

    private Disposable subscribe;

    @Override
    public void watcher() {
        log.info("以太坊 - 冻结事件监听");

        // 创建一个过滤器，用于监听 USDT 合约中 "AddedBlackList" 事件日志（Log）
        // 参数说明：
        // - fromBlock: 起始监听区块（这里是 LATEST，表示从最新的区块开始）
        // - toBlock: 结束监听区块（也是 LATEST，表示持续监听后续最新区块）
        // - address: 事件来源的合约地址（即 USDT 合约地址）
        EthFilter ethFilter = new EthFilter(EARLIEST, LATEST, properties.getConcatAddress());

        // 添加事件主题（topic）过滤，只监听 "AddedBlackList" 这个特定事件
        // 事件签名通过 EventEncoder.encode(ADDED_BLACKLIST_EVENT) 得到 Keccak-256("AddedBlackList(address)") 的前 4 字节
        Event blacklistEvent = new Event(EthConstants.BLACK_LIST_EVENT_NAME, List.of(new TypeReference<Address>(true) {}));
        String blacklistEventHash = EventEncoder.encode(blacklistEvent);

        // 可以监听多个事件 topic
        ethFilter.addSingleTopic(blacklistEventHash);

        //订阅监听
        this.subscribe = web3j.ethLogFlowable(ethFilter)
                              .subscribe(this::watcherPostHandle, ERROR_FUNC);
    }

    private void watcherPostHandle(Log watcherLog) {
        // 获取添加到黑名单地址
        String data = watcherLog.getData();

        // 获取最后 40 个字符（即 20 字节地址）
        String hexAddress = "0x" + data.substring(data.length() - 40);

        // 发送通知
        notifyFactory.getStrategy().freezeAddress(NotifySourceEnum.ETH, hexAddress);
    }


    @Override
    public void dispose() {
        if (this.subscribe != null && !this.subscribe.isDisposed()) {
            this.subscribe.dispose();
        }
    }
}
